跳到主要内容

缓存雪崩、击穿、穿透

马士兵金三银四 - Redis 面试题

缓存雪崩 - 应对策略

  • 大量数据同时过期
    1. 均匀设置过期时间
      对缓存数据设置过期时间时,给过期时间加上随机数,保证数据不会在同一时间过期
    2. 互斥锁
      当业务线程处理用户请求时,如果发现用户访问的数据不再 Redis 中,就加个互斥锁,保证同一时间只有一个请求构建缓存,缓存构建完成后再释放锁,未能获取互斥锁的请求等待锁释放后重新读取缓存,或者返回 空/默认值
      实现互斥锁时最好设置超时时间,防止请求异常阻塞锁无法释放,导致系统无响应
    3. 双 key 策略
      对缓存数据使用两个 key,主 key 设置过期时间,备 key 不设置过期时间,相当于数据副本
      当业务线程访问不到主 key 的缓存数据时,直接返回备 key 的数据,更新数据时主备 key 同时更新
      优点:可以快速相应请求,不会因为 key 失效导致大量请求被锁阻塞住(互斥锁),后续再通知后台线程重新构建主 key 数据
    4. 后台更新缓存
      缓存不设置有效期,业务线程不再负责更新缓存,将更新缓存的工作交给后台线程定时更新
      但是当系统内存紧张时,有些缓存数据会被淘汰,此时业务线程读取缓存失败,在业务的视角里就是缓存丢失了
      解决方案
    5. 后台线程不仅负责定时更新缓存,同时负责检查缓存是否有效,失效时马上重新载入缓存
    6. 业务线程发现缓存数据失效后(被淘汰),通过消息队列发送一条消息通知后台线程更新缓存,后台线程接收到消息后判断缓存是否存在,存在则不更新,不存在则重新获取缓存。 相比于第一种方案,缓存更新较及时,用户体验较好
  • Redis 故障宕机
    1. 服务熔断或请求限流
      故障宕机导致缓存雪崩时,启动服务熔断机制,暂停业务应用对缓存服务的访问,直接返回错误,不再访问数据库,从而降低对数据库的访问压力,保证数据库的正常运行,等 Redis 恢复后再允许业务访问
      服务熔断机制保护了数据库,但是暂停了业务对缓存系统的访问,会导致业务无法正常工作
      为了减少对业务的影响可以使用 请求限流 机制,只发送少量请求到数据库进行处理,再多的请求则在入口处拒绝服务,等 Redis 恢复正常并预热缓存后,再解除请求限流
    2. 构建 Redis 高可用集群
      使用主从节点构建 Redis 集群,避免故障宕机导致的缓存雪崩

缓存击穿 - 解决方案

  • 互斥锁
  • 不给热点数据设置过期时间,由后台异步更新缓存

缓存穿透 - 解决方案

  1. 限制非法请求
  2. 缓存 空/默认值
  3. 布隆过滤器